home *** CD-ROM | disk | FTP | other *** search
/ Developer CD Series 1999 October: Technology Seed / ADC Seed CD - October 1999.toast / FireWire / FireWire_2.0_SDK / Source / AVTransport / AVTransportTrafficLight / AVTransportTrafficLight.c next >
Encoding:
C/C++ Source or Header  |  1999-04-12  |  44.1 KB  |  1,977 lines  |  [TEXT/MPS ]

  1. /*
  2.     File:        AVTransportTrafficLight.c
  3.  
  4.     Contains:    Application software to control AV transport mechanisms.
  5.  
  6.     Written by:    Erik Staats with help from DTS.
  7.  
  8.     Copyright:    © 1996-1997 by Apple Computer, Inc., all rights reserved.
  9.  
  10.     Change History (most recent first):
  11.  
  12.       <FW10>     3/18/97    ES        Changed to not create new window if we get device added
  13.                                     notification for a device we already have open.
  14.        <FW9>      2/7/97    ES        Added call to GetNextAVTClientEvent in event loop.
  15.        <FW8>     8/26/96    ES        Changed to call QuitApplication if we quit on error.
  16.        <FW7>      8/1/96    ES        Took out unused local variables.
  17.        <FW6>     7/31/96    ES        Added dumpBufferOffset to avtDumpParams.
  18.        <FW5>      7/8/96    ES        Added extra menu and added snap shot grabbing and playing
  19.                                     capabilities.
  20.        <FW4>     6/21/96    ES        Changed some of the window stuff so this will work with MPW 3.4.
  21.        <FW3>     6/20/96    ES        Modified contains field.
  22.        <FW2>     6/20/96    ES        Filled in contains and written by fields.
  23.        <FW1>     6/20/96    ES        first checked in
  24.  
  25. */
  26.  
  27. #include <Types.h>
  28. #include <Memory.h>
  29. #include <Devices.h>
  30. #include <Resources.h>
  31. #include <QuickDraw.h>
  32. #include <Fonts.h>
  33. #include <Events.h>
  34. #include <AppleEvents.h>
  35. #include <EPPC.h>
  36. #include <Windows.h>
  37. #include <Menus.h>
  38. #include <Dialogs.h>
  39. #include <ToolUtils.h>
  40. #include <DiskInit.h>
  41. #include <AVTransport.h>
  42. #include <AVTransportTrafficLight.h>
  43.  
  44. ////////////////////////////////////////////////////////////////////////////////
  45. //
  46. // Define global structure to hold all of the AVTTrafficLight data.
  47. //
  48.  
  49. AVTTrafficLightAppDataPtr        gpAVTTrafficLightAppData = nil;
  50. Boolean                            quitTrafficLightApp = false;
  51.  
  52.  
  53. ////////////////////////////////////////////////////////////////////////////////
  54. //
  55. // Internal procedure prototypes.
  56. //
  57.  
  58. static void    AVTTrafficLightEventLoop (void);
  59.  
  60. static OSErr    HandleEvent (
  61.     EventRecord                    *pEventRecord);
  62.  
  63. static OSErr    HandleMouseDownEvent (
  64.     EventRecord                    *pEventRecord);
  65.  
  66. static OSErr    HandleKeyEvent (
  67.     EventRecord                    *pEventRecord);
  68.  
  69. static OSErr    HandleOSEvent (
  70.     EventRecord                    *pEventRecord);
  71.  
  72. static OSErr    HandleMenuCommand (
  73.     long                        menuCommand);
  74.  
  75. static OSErr    HandleAppleMenuCommand (
  76.     short                        menuItem);
  77.  
  78. static OSErr    HandleFileMenuCommand (
  79.     short                        menuItem);
  80.  
  81. static OSErr    HandleExtraMenuCommand (
  82.     short                        menuItem);
  83.  
  84. static OSErr    HandleCloseFileMenuCommand (void);
  85.  
  86. static OSErr    CaptureSnapShot (void);
  87.  
  88. static OSErr    PlaySnapShot (void);
  89.  
  90. static OSErr    StopSnapShot (void);
  91.  
  92. static OSErr    HandleWindowCommand (
  93.     WindowRef                    windowRef);
  94.  
  95. static OSErr    AVTTrafficLightInitialize (void);
  96.  
  97. static OSErr    QuitApplication (void);
  98.  
  99. static OSErr    CreateTrafficLight (
  100.     AVTDriverID                    avtDriverID);
  101.  
  102. static OSErr    RemoveTrafficLight (
  103.     AVTDriverID                    avtDriverID);
  104.  
  105. static OSErr    CloseTrafficLightWindow (
  106.     WindowRef                    windowRef);
  107.  
  108. static OSErr    DrawTrafficLight (
  109.     WindowRef                    windowRef);
  110.  
  111. static OSErr    SetTrafficLightState (
  112.     WindowRef                    windowRef,
  113.     Boolean                        stopped);
  114.  
  115. static Boolean    GetTrafficLightState (
  116.     WindowRef                    windowRef);
  117.  
  118. static OSErr    UpdateWindow (
  119.     WindowRef                    windowRef);
  120.  
  121. static OSErr    UpdateMenus (void);
  122.  
  123. static OSErr    UpdateCursor (
  124.     Point                        mousePosition,
  125.     RgnHandle                    hCursorRgn);
  126.  
  127. static Boolean    IsTrafficLightWindow (
  128.     WindowRef                    windowRef);
  129.  
  130. static void    GetMousePosition (
  131.     Point                        *pMousePosition);
  132.  
  133. static pascal OSErr    HandleOpenApplicationEvent (
  134.     AppleEvent                    *theAppleEvent,
  135.     AppleEvent                    *reply,
  136.     long                        handlerRefcon);
  137.  
  138. static pascal OSErr    HandleOpenDocumentsEvent (
  139.     AppleEvent                    *theAppleEvent,
  140.     AppleEvent                    *reply,
  141.     long                        handlerRefcon);
  142.  
  143. static pascal OSErr    HandlePrintDocumentsEvent (
  144.     AppleEvent                    *theAppleEvent,
  145.     AppleEvent                    *reply,
  146.     long                        handlerRefcon);
  147.  
  148. static pascal OSErr    HandleQuitApplicationEvent (
  149.     AppleEvent                    *theAppleEvent,
  150.     AppleEvent                    *reply,
  151.     long                        handlerRefcon);
  152.  
  153. static pascal OSErr    HandleDeviceAddedEvent (
  154.     AppleEvent                    *theAppleEvent,
  155.     AppleEvent                    *reply,
  156.     long                        handlerRefcon);
  157.  
  158. static pascal OSErr    HandleDeviceRemovedEvent (
  159.     AppleEvent                    *theAppleEvent,
  160.     AppleEvent                    *reply,
  161.     long                        handlerRefcon);
  162.  
  163. static TrafficLightDataPtr    FindTrafficLightFromAVTDriver (
  164.     AVTDriverID                    avtDriverID);
  165.  
  166. static OSErr    RemoveTrafficLightFromList (
  167.     TrafficLightDataPtr            pTrafficLightData);
  168.  
  169. static OSErr    PrepareWindowForUpdating (
  170.     WindowRef                    windowRef,
  171.     Boolean                        *pUpdateNeeded);
  172.  
  173. static OSErr    ReleaseWindowFromUpdating (
  174.     WindowRef                    windowRef);
  175.  
  176.  
  177. ////////////////////////////////////////////////////////////////////////////////
  178. ////////////////////////////////////////////////////////////////////////////////
  179. //
  180. // Exported routines.
  181. //
  182. ////////////////////////////////////////////////////////////////////////////////
  183. ////////////////////////////////////////////////////////////////////////////////
  184.  
  185. ////////////////////////////////////////////////////////////////////////////////
  186. //
  187. // AVTTrafficLightMain
  188. //
  189. //   This routine is the main entry point for the AVTransportTrafficLight
  190. // application.
  191. //
  192.  
  193. AVTTrafficLightMain()
  194. {
  195.     OSErr                        err = noErr;
  196.  
  197.     // Initialize the application.
  198.     err = AVTTrafficLightInitialize ();
  199.  
  200.     // Main application event loop.
  201.     if (err == noErr)
  202.         AVTTrafficLightEventLoop ();
  203.  
  204.     // Dispose of app data.
  205.     if (gpAVTTrafficLightAppData != nil)
  206.         QuitApplication ();
  207.  
  208.     return (err);
  209. }
  210.  
  211.  
  212. ////////////////////////////////////////////////////////////////////////////////
  213. ////////////////////////////////////////////////////////////////////////////////
  214. //
  215. // Internal routines.
  216. //
  217. ////////////////////////////////////////////////////////////////////////////////
  218. ////////////////////////////////////////////////////////////////////////////////
  219.  
  220. ////////////////////////////////////////////////////////////////////////////////
  221. //
  222. // AVTTrafficLightEventLoop
  223. //
  224. //   This routine is the main event loop for the AVTransportTrafficLight
  225. // application.
  226. //
  227.  
  228. static void    AVTTrafficLightEventLoop(void)
  229. {
  230.     RgnHandle                    hCursorRgn;
  231.     Point                        mousePosition;
  232.     EventRecord                    eventRecord;
  233.     Boolean                        gotEvent;
  234.     OSErr                        err = noErr;
  235.  
  236.     // Initialize cursor region.
  237.     hCursorRgn = NewRgn ();
  238.     if (hCursorRgn == nil)
  239.         err = memFullErr;//zzz is this right?
  240.  
  241.     // Main event loop.
  242.     while ((!quitTrafficLightApp) && (err == noErr))
  243.     {
  244.         // Update cursor to correct image.
  245.         GetMousePosition (&mousePosition);
  246.         err = UpdateCursor (mousePosition, hCursorRgn);
  247.  
  248.         // Get any AVTransport events.
  249.         if (err == noErr)
  250.             err = GetNextAVTClientEvent (gpAVTTrafficLightAppData->avtClientID);
  251.  
  252.         // Wait for next event.
  253.         if (err == noErr)
  254.             gotEvent = WaitNextEvent (everyEvent, &eventRecord, 0, hCursorRgn);
  255.  
  256.         // Handle event if we got one.
  257.         if (err == noErr)
  258.         {
  259.             if (gotEvent)
  260.             {
  261.                 // Update cursor to correct image.
  262.                 err = UpdateCursor (eventRecord.where, hCursorRgn);
  263.     
  264.                 // Handle the event.
  265.                 if (err == noErr)
  266.                     err = HandleEvent (&eventRecord);
  267.             }
  268.         }
  269.     }
  270. }
  271.  
  272.  
  273. ////////////////////////////////////////////////////////////////////////////////
  274. //
  275. // HandleEvent
  276. //
  277. //   This routine handles the given event.
  278. //
  279.  
  280. static OSErr    HandleEvent(
  281.     EventRecord                    *pEventRecord)
  282. {
  283.     Point                        point;
  284.     OSErr                        err = noErr;
  285.  
  286.     // Main event dispatcher.
  287.     switch (pEventRecord->what)
  288.     {
  289.         case mouseDown :
  290.             err = HandleMouseDownEvent (pEventRecord);
  291.             break;
  292.  
  293.         case keyDown :
  294.         case autoKey :
  295.             err = HandleKeyEvent (pEventRecord);
  296.             break;
  297.  
  298.         case updateEvt :
  299.             err = UpdateWindow ((WindowRef) (pEventRecord->message));
  300.             break;
  301.  
  302.         case diskEvt :
  303.             if ((pEventRecord->message >> 16) != noErr)
  304.             {
  305.                 SetPt (&point, kDILeft, kDITop);
  306.                 err = DIBadMount (point, pEventRecord->message);
  307.             }
  308.             break;
  309.  
  310.         case osEvt :
  311.             err = HandleOSEvent (pEventRecord);
  312.             break;
  313.  
  314.         case kHighLevelEvent :
  315.             AEProcessAppleEvent (pEventRecord);
  316.             break;
  317.  
  318.         default :
  319.             break;
  320.     }
  321.  
  322.     return (err);
  323. }
  324.  
  325.  
  326. ////////////////////////////////////////////////////////////////////////////////
  327. //
  328. // HandleMouseDownEvent
  329. //
  330. //   This routine handles mouse down events.
  331. //
  332.  
  333. static OSErr    HandleMouseDownEvent(
  334.     EventRecord                    *pEventRecord)
  335. {
  336.     WindowRef                    windowRef;
  337.     short                        inPart;
  338.     OSErr                        err = noErr;
  339.  
  340.     // Find out what part of application mouse is in.
  341.     inPart = FindWindow (pEventRecord->where, &windowRef);
  342.  
  343.     // Dispatch off of inPart.
  344.     switch (inPart)
  345.     {
  346.         case inMenuBar :
  347.             UpdateMenus ();
  348.             err = HandleMenuCommand (MenuSelect (pEventRecord->where));
  349.             break;
  350.  
  351.         case inSysWindow :
  352.             SystemClick (pEventRecord, windowRef);
  353.             break;
  354.  
  355.         case inContent :
  356.             if (windowRef == FrontWindow ())
  357.                 err = HandleWindowCommand (windowRef);
  358.             else
  359.                 SelectWindow (windowRef);
  360.             break;
  361.  
  362.         case inDrag :
  363.             DragWindow
  364.                 (windowRef,
  365.                  pEventRecord->where,
  366.                  &(gpAVTTrafficLightAppData->qdGlobals.screenBits.bounds));
  367.             break;
  368.  
  369.         case inGoAway :
  370.             if (TrackGoAway (windowRef, pEventRecord->where))
  371.                 CloseTrafficLightWindow (windowRef);
  372.             break;
  373.  
  374.         default :
  375.             break;
  376.     }
  377.  
  378.     return (err);
  379. }
  380.  
  381.  
  382. ////////////////////////////////////////////////////////////////////////////////
  383. //
  384. // HandleKeyEvent
  385. //
  386. //   This routine handles key events.
  387. //
  388.  
  389. static OSErr    HandleKeyEvent(
  390.     EventRecord                    *pEventRecord)
  391. {
  392.     char                        key;
  393.     OSErr                        err = noErr;
  394.  
  395.     // Read the key from the event record.
  396.     key = pEventRecord->message & charCodeMask;
  397.  
  398.     // We're only interested in command key down events.
  399.     if ((pEventRecord->modifiers & cmdKey) &&
  400.         (pEventRecord->what == keyDown))
  401.     {
  402.         UpdateMenus ();
  403.         err = HandleMenuCommand (MenuKey (key));
  404.     }
  405.  
  406.     return (err);
  407. }
  408.  
  409.  
  410. ////////////////////////////////////////////////////////////////////////////////
  411. //
  412. // HandleOSEvent
  413. //
  414. //   This routine handles OS events.
  415. //
  416.  
  417. static OSErr    HandleOSEvent(
  418.     EventRecord                    *pEventRecord)
  419. {
  420.     UInt32                        osEventType;
  421.     OSErr                        err = noErr;
  422.  
  423.     // Get the OS event type.
  424.     osEventType = pEventRecord->message >> 24;
  425.  
  426.     // Dispatch.
  427.     switch (osEventType)
  428.     {
  429.         case suspendResumeMessage :
  430.             if (pEventRecord->message & resumeFlag)
  431.                 gpAVTTrafficLightAppData->inForeground = true;
  432.             else
  433.                 gpAVTTrafficLightAppData->inForeground = false;
  434.             break;
  435.  
  436.         default :
  437.             break;
  438.     }
  439.  
  440.     return (err);
  441. }
  442.  
  443.  
  444. ////////////////////////////////////////////////////////////////////////////////
  445. //
  446. // HandleMenuCommand
  447. //
  448. //   This routine handles menu commands.
  449. //
  450.  
  451. static OSErr    HandleMenuCommand(
  452.     long                        menuCommand)
  453. {
  454.     short                        menuID,
  455.                                 menuItem;
  456.     OSErr                        err = noErr;
  457.  
  458.     // Get menu ID and item number from the menu command.
  459.     menuID = menuCommand >> 16;
  460.     menuItem = menuCommand & 0xFFFF;
  461.  
  462.     // Dispatch off of menu ID.
  463.     switch (menuID)
  464.     {
  465.         case kAppleMenuID :
  466.             err = HandleAppleMenuCommand (menuItem);
  467.             break;
  468.  
  469.         case kFileMenuID :
  470.             err = HandleFileMenuCommand (menuItem);
  471.             break;
  472.  
  473.         case kEditMenuID :
  474.             // Don't know if we'll ever get here.
  475.             SystemEdit (menuItem - 1);
  476.             break;
  477.  
  478.         case kExtraMenuID :
  479.             err = HandleExtraMenuCommand (menuItem);
  480.             break;
  481.  
  482.         default :
  483.             break;
  484.     }
  485.  
  486.     // Unhilite menu.
  487.     HiliteMenu (0);
  488.  
  489.     return (err);
  490. }
  491.  
  492.  
  493. ////////////////////////////////////////////////////////////////////////////////
  494. //
  495. // HandleAppleMenuCommand
  496. //
  497. //   This routine handles apple menu commands.
  498. //
  499.  
  500. static OSErr    HandleAppleMenuCommand(
  501.     short                        menuItem)
  502. {
  503.     Str255                        daName;
  504.     OSErr                        err = noErr;
  505.  
  506.     // Apple menu dispatch.
  507.     switch (menuItem)
  508.     {
  509.         case kAboutAppleMenuItem :
  510.             Alert (kAboutAlertResourceID, nil);
  511.             break;
  512.  
  513.         default :
  514.             // All non-about items are DAs.
  515.             GetMenuItemText (GetMenuHandle (kAppleMenuID), menuItem, daName);
  516.             OpenDeskAcc (daName);
  517.             break;
  518.     }
  519.  
  520.     return (err);
  521. }
  522.  
  523.  
  524. ////////////////////////////////////////////////////////////////////////////////
  525. //
  526. // HandleFileMenuCommand
  527. //
  528. //   This routine handles file menu commands.
  529. //
  530.  
  531. static OSErr    HandleFileMenuCommand(
  532.     short                        menuItem)
  533. {
  534.     OSErr                        err = noErr;
  535.  
  536.     // File menu dispatch.
  537.     switch (menuItem)
  538.     {
  539.         case kCloseFileMenuItem :
  540.             HandleCloseFileMenuCommand ();
  541.             break;
  542.  
  543.         case kQuitFileMenuItem :
  544.             QuitApplication ();
  545.             break;
  546.  
  547.         default :
  548.             break;
  549.     }
  550.  
  551.     return (err);
  552. }
  553.  
  554.  
  555. ////////////////////////////////////////////////////////////////////////////////
  556. //
  557. // HandleExtraMenuCommand
  558. //
  559. //   This routine handles extra menu commands.
  560. //
  561.  
  562. static OSErr    HandleExtraMenuCommand(
  563.     short                        menuItem)
  564. {
  565.     OSErr                        err = noErr;
  566.  
  567.     // File menu dispatch.
  568.     switch (menuItem)
  569.     {
  570.         case kCaptureSnapShotMenuItem :
  571.             err = CaptureSnapShot ();
  572.             break;
  573.  
  574.         case kPlaySnapShotMenuItem :
  575.             err = PlaySnapShot ();
  576.             break;
  577.  
  578.         case kStopSnapShotMenuItem :
  579.             err = StopSnapShot ();
  580.             break;
  581.  
  582.         default :
  583.             break;
  584.     }
  585.  
  586.     return (err);
  587. }
  588.  
  589.  
  590. ////////////////////////////////////////////////////////////////////////////////
  591. //
  592. // HandleCloseFileMenuCommand
  593. //
  594. //   This routine handles the close command.
  595. //
  596.  
  597. static OSErr    HandleCloseFileMenuCommand(void)
  598. {
  599.     WindowRef                    windowRef;
  600.     OSErr                        err = noErr;
  601.  
  602.     // Get reference to front most window and close.
  603.     windowRef = FrontWindow ();
  604.     if (windowRef != kInvalidWindowRef)
  605.         err = CloseTrafficLightWindow (windowRef);
  606.     
  607.     return (err);
  608. }
  609.  
  610.  
  611. ////////////////////////////////////////////////////////////////////////////////
  612. //
  613. // CaptureSnapShot
  614. //
  615. //   This routine captures a snap shot picture from the camera.
  616. //
  617.  
  618. static OSErr    CaptureSnapShot(void)
  619. {
  620.     WindowRef                    windowRef;
  621.     MenuHandle                    hMenu;
  622.     TrafficLightDataPtr            pTrafficLightData;
  623.     AVTDumpParams                avtDumpParams;
  624.     OSErr                        err = noErr;
  625.  
  626.     // Get reference to front most window and close.
  627.     windowRef = FrontWindow ();
  628.     if (windowRef != kInvalidWindowRef)
  629.     {
  630.         // Get traffic light data.
  631.         pTrafficLightData = (TrafficLightDataPtr) GetWRefCon (windowRef);
  632.  
  633.         // Stop playing snap shot if it's playing.
  634.         if (pTrafficLightData->snapShotPlaying)
  635.             err = StopSnapShot ();
  636.  
  637.         // Capture a snap shot.
  638.         if (err == noErr)
  639.         {
  640.             avtDumpParams.avtInterfaceParams.interfaceSelector =
  641.                 kAVTransportDump;
  642.             avtDumpParams.dumpBuffer =
  643.                 gpAVTTrafficLightAppData->dumpBuffer;
  644.             avtDumpParams.dumpBufferSize =
  645.                 gpAVTTrafficLightAppData->dumpBufferSize;
  646.             avtDumpParams.dumpBufferOffset = 0;
  647.     
  648.             err = CallAVTDriver
  649.                     (pTrafficLightData->avtDriverID,
  650.                      (AVTInterfaceParamsPtr) &avtDumpParams);
  651.         }
  652.  
  653.         // Enable playing snap shot if we hadn't already gotten one.
  654.         if ((err == noErr) && (!(gpAVTTrafficLightAppData->gotSnapShot)))
  655.         {
  656.             hMenu = GetMenuHandle (kExtraMenuID);
  657.  
  658.             if (hMenu != nil)
  659.             {
  660.                 EnableItem (hMenu, kPlaySnapShotMenuItem);
  661.                 gpAVTTrafficLightAppData->gotSnapShot = true;
  662.             }
  663.         }
  664.     }
  665.     
  666.     return (err);
  667. }
  668.  
  669.  
  670. ////////////////////////////////////////////////////////////////////////////////
  671. //
  672. // PlaySnapShot
  673. //
  674. //   This routine plays a snap shot picture to the camera.
  675. //
  676.  
  677. static OSErr    PlaySnapShot(void)
  678. {
  679.     WindowRef                    windowRef;
  680.     MenuHandle                    hMenu;
  681.     TrafficLightDataPtr            pTrafficLightData;
  682.     AVTPlaySnapShotParams        avtPlaySnapShotParams;
  683.     OSErr                        err = noErr;
  684.  
  685.     // Get reference to front most window and close.
  686.     windowRef = FrontWindow ();
  687.     if (windowRef != kInvalidWindowRef)
  688.     {
  689.         // Get traffic light data.
  690.         pTrafficLightData = (TrafficLightDataPtr) GetWRefCon (windowRef);
  691.  
  692.         // Play a snap shot.
  693.         if ((!(pTrafficLightData->snapShotPlaying)) &&
  694.             (gpAVTTrafficLightAppData->gotSnapShot))
  695.         {
  696.             avtPlaySnapShotParams.avtInterfaceParams.interfaceSelector =
  697.                 kAVTransportPlaySnapShot;
  698.             avtPlaySnapShotParams.snapShotBuffer =
  699.                 gpAVTTrafficLightAppData->dumpBuffer;
  700.             avtPlaySnapShotParams.snapShotBufferSize =
  701.                 gpAVTTrafficLightAppData->dumpBufferSize;
  702.  
  703.             err = CallAVTDriver
  704.                     (pTrafficLightData->avtDriverID,
  705.                      (AVTInterfaceParamsPtr) &avtPlaySnapShotParams);
  706.  
  707.             // Enable stopping snap shot.
  708.             if (err == noErr)
  709.             {
  710.                 hMenu = GetMenuHandle (kExtraMenuID);
  711.                 if (hMenu != nil)
  712.                 {
  713.                     DisableItem (hMenu, kPlaySnapShotMenuItem);
  714.                     EnableItem (hMenu, kStopSnapShotMenuItem);
  715.                 }
  716.  
  717.                 pTrafficLightData->snapShotPlaying = true;
  718.             }
  719.         }
  720.     }
  721.     
  722.     return (err);
  723. }
  724.  
  725.  
  726. ////////////////////////////////////////////////////////////////////////////////
  727. //
  728. // StopSnapShot
  729. //
  730. //   This routine stops playing a snap shot picture to the camera.
  731. //
  732.  
  733. static OSErr    StopSnapShot(void)
  734. {
  735.     WindowRef                    windowRef;
  736.     MenuHandle                    hMenu;
  737.     TrafficLightDataPtr            pTrafficLightData;
  738.     AVTInterfaceParams            avtInterfaceParams;
  739.     OSErr                        err = noErr;
  740.  
  741.     // Get reference to front most window and close.
  742.     windowRef = FrontWindow ();
  743.     if (windowRef != kInvalidWindowRef)
  744.     {
  745.         // Get traffic light data.
  746.         pTrafficLightData = (TrafficLightDataPtr) GetWRefCon (windowRef);
  747.  
  748.         // Play a snap shot.
  749.         if (pTrafficLightData->snapShotPlaying)
  750.         {
  751.             avtInterfaceParams.interfaceSelector = kAVTransportStopSnapShot;
  752.  
  753.             err = CallAVTDriver
  754.                     (pTrafficLightData->avtDriverID, &avtInterfaceParams);
  755.  
  756.             // Enable playing snap shot.
  757.             if (err == noErr)
  758.             {
  759.                 hMenu = GetMenuHandle (kExtraMenuID);
  760.                 if (hMenu != nil)
  761.                 {
  762.                     DisableItem (hMenu, kStopSnapShotMenuItem);
  763.                     EnableItem (hMenu, kPlaySnapShotMenuItem);
  764.                 }
  765.  
  766.                 pTrafficLightData->snapShotPlaying = false;
  767.             }
  768.         }
  769.     }
  770.     
  771.     return (err);
  772. }
  773.  
  774.  
  775. ////////////////////////////////////////////////////////////////////////////////
  776. //
  777. // HandleWindowCommand
  778. //
  779. //   This routine handles commands in the contents of the window.
  780. //
  781.  
  782. static OSErr    HandleWindowCommand(
  783.     WindowRef                    windowRef)
  784. {
  785.     OSErr                        err = noErr;
  786.  
  787.     // Toggle the traffic light state.
  788.     err = SetTrafficLightState (windowRef, !(GetTrafficLightState (windowRef)));
  789.  
  790.     return (err);
  791. }
  792.  
  793.  
  794. ////////////////////////////////////////////////////////////////////////////////
  795. //
  796. // AVTTrafficLightInitialize
  797. //
  798. //   This routine initializes the AVTransportTrafficLight application.
  799. //
  800.  
  801. static OSErr    AVTTrafficLightInitialize(void)
  802. {
  803.     Handle                        hMenuBarResource;
  804.     Handle                        hRectResource;
  805.     AVTDriverID                    *avtDriverIDList = nil;
  806.     UInt32                        numAVTDrivers,
  807.                                 driverNum;
  808.     Ptr                            dumpBuffer;
  809.     OSErr                        err = noErr;
  810.  
  811.     // Create our global data record.
  812.     gpAVTTrafficLightAppData = (AVTTrafficLightAppDataPtr)
  813.         NewPtrClear (sizeof (AVTTrafficLightAppData));
  814.     if (gpAVTTrafficLightAppData != nil)
  815.     {
  816.         gpAVTTrafficLightAppData->avtClientID = kInvalidAVTClientID;
  817.         gpAVTTrafficLightAppData->inForeground = true;
  818.     }
  819.     else
  820.     {
  821.         err = memFullErr;
  822.     }
  823.  
  824.     // Initialize a bunch of managers.
  825.     if (err == noErr)
  826.     {
  827.         InitGraf ((Ptr) &(gpAVTTrafficLightAppData->qdGlobals.thePort));
  828.         InitFonts ();
  829.         InitWindows ();
  830.         InitMenus ();
  831.         InitDialogs (nil);
  832.         InitCursor ();
  833.     }
  834.  
  835.     // Create our menu bar using the defs in our resources.
  836.     if (err == noErr)
  837.     {
  838.         hMenuBarResource = GetNewMBar (kMenuBarResourceID);
  839.         if (hMenuBarResource != nil)
  840.         {
  841.             SetMenuBar (hMenuBarResource);
  842.             DisposeHandle (hMenuBarResource);
  843.             AppendResMenu (GetMenuHandle (kAppleMenuID), 'DRVR');
  844.             DrawMenuBar ();
  845.         }
  846.         else
  847.         {
  848.             err = memFullErr;//zzz what should it really be?
  849.         }
  850.     }
  851.  
  852.     // Get rects for lights.
  853.     if (err == noErr)
  854.     {
  855.         hRectResource = GetResource ('RECT', kStopRectResourceID);
  856.         if (hRectResource != nil)
  857.         {
  858.             gpAVTTrafficLightAppData->stopRect = *((Rect *) (*hRectResource));
  859.             ReleaseResource (hRectResource);
  860.         }
  861.         else
  862.         {
  863.             err = ResError ();
  864.             if (err == noErr)
  865.                 err = resNotFound;
  866.         }
  867.  
  868.         if (err == noErr)
  869.         {
  870.             hRectResource = GetResource ('RECT', kGoRectResourceID);
  871.             if (hRectResource != nil)
  872.             {
  873.                 gpAVTTrafficLightAppData->goRect = *((Rect *) (*hRectResource));
  874.                 ReleaseResource (hRectResource);
  875.             }
  876.             else
  877.             {
  878.                 err = ResError ();
  879.                 if (err == noErr)
  880.                     err = resNotFound;
  881.             }
  882.         }
  883.     }
  884.  
  885.     // Create open application event handler.
  886.     if (err == noErr)
  887.     {
  888.         gpAVTTrafficLightAppData->openApplicationEventHandler =
  889.             NewAEEventHandlerProc (HandleOpenApplicationEvent);
  890.         if (gpAVTTrafficLightAppData->openApplicationEventHandler == nil)
  891.             err = memFullErr;
  892.     }
  893.  
  894.     // Install handler.
  895.     if (err == noErr)
  896.     {
  897.         err = AEInstallEventHandler
  898.                 (kCoreEventClass,
  899.                  kAEOpenApplication,
  900.                  gpAVTTrafficLightAppData->openApplicationEventHandler,
  901.                  (long) gpAVTTrafficLightAppData,
  902.                  false);
  903.         if (err == noErr)
  904.         {
  905.             gpAVTTrafficLightAppData->openApplicationEventHandlerInstalled =
  906.                 true;
  907.         }
  908.     }
  909.  
  910.     // Create open documents event handler.
  911.     if (err == noErr)
  912.     {
  913.         gpAVTTrafficLightAppData->openDocumentsEventHandler =
  914.             NewAEEventHandlerProc (HandleOpenDocumentsEvent);
  915.         if (gpAVTTrafficLightAppData->openDocumentsEventHandler == nil)
  916.             err = memFullErr;
  917.     }
  918.  
  919.     // Install handler.
  920.     if (err == noErr)
  921.     {
  922.         err = AEInstallEventHandler
  923.                 (kCoreEventClass,
  924.                  kAEOpenDocuments,
  925.                  gpAVTTrafficLightAppData->openDocumentsEventHandler,
  926.                  (long) gpAVTTrafficLightAppData,
  927.                  false);
  928.         if (err == noErr)
  929.         {
  930.             gpAVTTrafficLightAppData->openDocumentsEventHandlerInstalled =
  931.                 true;
  932.         }
  933.     }
  934.  
  935.     // Create print documents event handler.
  936.     if (err == noErr)
  937.     {
  938.         gpAVTTrafficLightAppData->printDocumentsEventHandler =
  939.             NewAEEventHandlerProc (HandlePrintDocumentsEvent);
  940.         if (gpAVTTrafficLightAppData->printDocumentsEventHandler == nil)
  941.             err = memFullErr;
  942.     }
  943.  
  944.     // Install handler.
  945.     if (err == noErr)
  946.     {
  947.         err = AEInstallEventHandler
  948.                 (kCoreEventClass,
  949.                  kAEPrintDocuments,
  950.                  gpAVTTrafficLightAppData->printDocumentsEventHandler,
  951.                  (long) gpAVTTrafficLightAppData,
  952.                  false);
  953.         if (err == noErr)
  954.         {
  955.             gpAVTTrafficLightAppData->printDocumentsEventHandlerInstalled =
  956.                 true;
  957.         }
  958.     }
  959.  
  960.     // Create quit application event handler.
  961.     if (err == noErr)
  962.     {
  963.         gpAVTTrafficLightAppData->quitApplicationEventHandler =
  964.             NewAEEventHandlerProc (HandleQuitApplicationEvent);
  965.         if (gpAVTTrafficLightAppData->quitApplicationEventHandler == nil)
  966.             err = memFullErr;
  967.     }
  968.  
  969.     // Install handler.
  970.     if (err == noErr)
  971.     {
  972.         err = AEInstallEventHandler
  973.                 (kCoreEventClass,
  974.                  kAEQuitApplication,
  975.                  gpAVTTrafficLightAppData->quitApplicationEventHandler,
  976.                  (long) gpAVTTrafficLightAppData,
  977.                  false);
  978.         if (err == noErr)
  979.         {
  980.             gpAVTTrafficLightAppData->quitApplicationEventHandlerInstalled =
  981.                 true;
  982.         }
  983.     }
  984.  
  985.     // Create device added event handler.
  986.     if (err == noErr)
  987.     {
  988.         gpAVTTrafficLightAppData->deviceAddedEventHandler =
  989.             NewAEEventHandlerProc (HandleDeviceAddedEvent);
  990.         if (gpAVTTrafficLightAppData->deviceAddedEventHandler == nil)
  991.             err = memFullErr;
  992.     }
  993.  
  994.     // Install handler.
  995.     if (err == noErr)
  996.     {
  997.         err = AEInstallEventHandler
  998.                 (kAEAVTransportEventClass,
  999.                  kAEAVTransportDeviceAdded,
  1000.                  gpAVTTrafficLightAppData->deviceAddedEventHandler,
  1001.                  (long) gpAVTTrafficLightAppData,
  1002.                  false);
  1003.         if (err == noErr)
  1004.         {
  1005.             gpAVTTrafficLightAppData->deviceAddedEventHandlerInstalled =
  1006.                 true;
  1007.         }
  1008.     }
  1009.  
  1010.     // Create device removed event handler.
  1011.     if (err == noErr)
  1012.     {
  1013.         gpAVTTrafficLightAppData->deviceRemovedEventHandler =
  1014.             NewAEEventHandlerProc (HandleDeviceRemovedEvent);
  1015.         if (gpAVTTrafficLightAppData->deviceRemovedEventHandler == nil)
  1016.             err = memFullErr;
  1017.     }
  1018.  
  1019.     // Install handler.
  1020.     if (err == noErr)
  1021.     {
  1022.         err = AEInstallEventHandler
  1023.                 (kAEAVTransportEventClass,
  1024.                  kAEAVTransportDeviceRemoved,
  1025.                  gpAVTTrafficLightAppData->deviceRemovedEventHandler,
  1026.                  (long) gpAVTTrafficLightAppData,
  1027.                  false);
  1028.         if (err == noErr)
  1029.         {
  1030.             gpAVTTrafficLightAppData->deviceRemovedEventHandlerInstalled =
  1031.                 true;
  1032.         }
  1033.     }
  1034.  
  1035.     // Register with the AV transport control driver family.
  1036.     if (err == noErr)
  1037.     {
  1038.         err = RegisterAVTClientApplication
  1039.                 (&(gpAVTTrafficLightAppData->avtClientID),
  1040.                  (UInt32) gpAVTTrafficLightAppData);
  1041.     }
  1042.  
  1043.     // Get list of drivers.
  1044.     //zzz theoretically, new ones can be added while we're doing this.
  1045.     if (err == noErr)
  1046.         err = GetAVTDriverList (nil, 0, &numAVTDrivers);
  1047.  
  1048.     if ((err == noErr) && (numAVTDrivers > 0))
  1049.     {
  1050.         avtDriverIDList = (AVTDriverID *)
  1051.             NewPtr (numAVTDrivers * sizeof (AVTDriverID));
  1052.         if (avtDriverIDList != nil)
  1053.         {
  1054.             err = GetAVTDriverList
  1055.                     (avtDriverIDList, numAVTDrivers, &numAVTDrivers);
  1056.         }
  1057.         else
  1058.         {
  1059.             err = memFullErr;
  1060.         }
  1061.     }
  1062.  
  1063.     // Create a stop light for each driver.
  1064.     for (driverNum = 0;
  1065.          ((driverNum < numAVTDrivers) && (err == noErr));
  1066.          driverNum++)
  1067.     {
  1068.         err = CreateTrafficLight (avtDriverIDList[driverNum]);
  1069.     }
  1070.  
  1071.     // Allocate a buffer for video dumps.
  1072.     if (err == noErr)
  1073.     {
  1074.         dumpBuffer = NewPtr (kDumpBufferSize);
  1075.         if (dumpBuffer != nil)
  1076.         {
  1077.             gpAVTTrafficLightAppData->dumpBuffer = dumpBuffer;
  1078.             gpAVTTrafficLightAppData->dumpBufferSize = kDumpBufferSize;
  1079.         }
  1080.         else
  1081.         {
  1082.             err = memFullErr;
  1083.         }
  1084.     }
  1085.  
  1086.     // Clean up.
  1087.     if (avtDriverIDList != nil)
  1088.         DisposePtr ((Ptr) avtDriverIDList);
  1089.  
  1090.     return (err);
  1091. }
  1092.  
  1093.  
  1094. ////////////////////////////////////////////////////////////////////////////////
  1095. //
  1096. // QuitApplication
  1097. //
  1098. //   This routine quits the application.
  1099. //
  1100.  
  1101. static OSErr    QuitApplication(void)
  1102. {
  1103.     TrafficLightDataPtr            pTrafficLightData,
  1104.                                 pNextTrafficLightData;
  1105.     AVTClientID                    avtClientID;
  1106.     OSErr                        err = noErr;
  1107.  
  1108.     if (gpAVTTrafficLightAppData != nil)
  1109.     {
  1110.         // Deallocate video dump buffer.
  1111.         if (gpAVTTrafficLightAppData->dumpBuffer != nil)
  1112.             DisposePtr (gpAVTTrafficLightAppData->dumpBuffer);
  1113.  
  1114.         // Remove all of the traffic lights.
  1115.         pTrafficLightData = gpAVTTrafficLightAppData->trafficLightDataList;
  1116.         while (pTrafficLightData != nil)
  1117.         {
  1118.             pNextTrafficLightData = pTrafficLightData->pNextTrafficLightData;
  1119.     
  1120.             RemoveTrafficLight (pTrafficLightData->avtDriverID);
  1121.     
  1122.             pTrafficLightData = pNextTrafficLightData;
  1123.         }
  1124.     
  1125.         // Unregister with the AV transport control driver family.
  1126.         avtClientID = gpAVTTrafficLightAppData->avtClientID;
  1127.         if (avtClientID != kInvalidAVTClientID)
  1128.             UnregisterAVTClientApplication (avtClientID);
  1129.     
  1130.         // Uninstall Apple event handlers.
  1131.         // Uninstall device removed event handler.
  1132.         if (gpAVTTrafficLightAppData->deviceRemovedEventHandlerInstalled)
  1133.         {
  1134.             AERemoveEventHandler
  1135.                 (kAEAVTransportEventClass,
  1136.                  kAEAVTransportDeviceRemoved,
  1137.                  gpAVTTrafficLightAppData->deviceRemovedEventHandler,
  1138.                  false);
  1139.         }
  1140.  
  1141.         if (gpAVTTrafficLightAppData->deviceRemovedEventHandler != nil)
  1142.         {
  1143.             DisposeRoutineDescriptor
  1144.                 (gpAVTTrafficLightAppData->deviceRemovedEventHandler);
  1145.         }
  1146.  
  1147.         // Uninstall device added event handler.
  1148.         if (gpAVTTrafficLightAppData->deviceAddedEventHandlerInstalled)
  1149.         {
  1150.             AERemoveEventHandler
  1151.                 (kAEAVTransportEventClass,
  1152.                  kAEAVTransportDeviceAdded,
  1153.                  gpAVTTrafficLightAppData->deviceAddedEventHandler,
  1154.                  false);
  1155.         }
  1156.  
  1157.         if (gpAVTTrafficLightAppData->deviceAddedEventHandler != nil)
  1158.         {
  1159.             DisposeRoutineDescriptor
  1160.                 (gpAVTTrafficLightAppData->deviceAddedEventHandler);
  1161.         }
  1162.  
  1163.         // Uninstall quit application event handler.
  1164.         if (gpAVTTrafficLightAppData->quitApplicationEventHandlerInstalled)
  1165.         {
  1166.             AERemoveEventHandler
  1167.                 (kCoreEventClass,
  1168.                  kAEQuitApplication,
  1169.                  gpAVTTrafficLightAppData->quitApplicationEventHandler,
  1170.                  false);
  1171.         }
  1172.  
  1173.         if (gpAVTTrafficLightAppData->quitApplicationEventHandler != nil)
  1174.         {
  1175.             DisposeRoutineDescriptor
  1176.                 (gpAVTTrafficLightAppData->quitApplicationEventHandler);
  1177.         }
  1178.  
  1179.         // Uninstall print documents event handler.
  1180.         if (gpAVTTrafficLightAppData->printDocumentsEventHandlerInstalled)
  1181.         {
  1182.             AERemoveEventHandler
  1183.                 (kCoreEventClass,
  1184.                  kAEPrintDocuments,
  1185.                  gpAVTTrafficLightAppData->printDocumentsEventHandler,
  1186.                  false);
  1187.         }
  1188.  
  1189.         if (gpAVTTrafficLightAppData->printDocumentsEventHandler != nil)
  1190.         {
  1191.             DisposeRoutineDescriptor
  1192.                 (gpAVTTrafficLightAppData->printDocumentsEventHandler);
  1193.         }
  1194.  
  1195.         // Uninstall open documents event handler.
  1196.         if (gpAVTTrafficLightAppData->openDocumentsEventHandlerInstalled)
  1197.         {
  1198.             AERemoveEventHandler
  1199.                 (kCoreEventClass,
  1200.                  kAEOpenDocuments,
  1201.                  gpAVTTrafficLightAppData->openDocumentsEventHandler,
  1202.                  false);
  1203.         }
  1204.  
  1205.         if (gpAVTTrafficLightAppData->openDocumentsEventHandler != nil)
  1206.         {
  1207.             DisposeRoutineDescriptor
  1208.                 (gpAVTTrafficLightAppData->openDocumentsEventHandler);
  1209.         }
  1210.  
  1211.         // Uninstall open application event handler.
  1212.         if (gpAVTTrafficLightAppData->openApplicationEventHandlerInstalled)
  1213.         {
  1214.             AERemoveEventHandler
  1215.                 (kCoreEventClass,
  1216.                  kAEOpenApplication,
  1217.                  gpAVTTrafficLightAppData->openApplicationEventHandler,
  1218.                  false);
  1219.         }
  1220.  
  1221.         if (gpAVTTrafficLightAppData->openApplicationEventHandler != nil)
  1222.         {
  1223.             DisposeRoutineDescriptor
  1224.                 (gpAVTTrafficLightAppData->openApplicationEventHandler);
  1225.         }
  1226.  
  1227.         // Dispose of global data record.
  1228.         DisposePtr ((Ptr) gpAVTTrafficLightAppData);
  1229.         gpAVTTrafficLightAppData = nil;
  1230.  
  1231.         // Set event loop to quit.
  1232.         quitTrafficLightApp = true;
  1233.     }
  1234.  
  1235.     return (err);
  1236. }
  1237.  
  1238.  
  1239. ////////////////////////////////////////////////////////////////////////////////
  1240. //
  1241. // CreateTrafficLight
  1242. //
  1243. //   This routine creates a new traffic light window for the given driver.
  1244. //
  1245.  
  1246. static OSErr    CreateTrafficLight(
  1247.     AVTDriverID                    avtDriverID)
  1248. {
  1249.     WindowRef                    trafficLightWindowRef = kInvalidWindowRef;
  1250.     TrafficLightDataPtr            pTrafficLightData = nil;
  1251.     OSErr                        err = noErr;
  1252.  
  1253.     // Get a new stop light window.
  1254.     trafficLightWindowRef =
  1255.         GetNewWindow (kTrafficLightWindowResourceID, nil, (WindowRef) -1);
  1256.     if (trafficLightWindowRef == kInvalidWindowRef)
  1257.         err = -1;//zzz not really correct.
  1258.  
  1259.     // Allocate traffic light data record.
  1260.     if (err == noErr)
  1261.     {
  1262.         pTrafficLightData =
  1263.             (TrafficLightDataPtr) NewPtrClear (sizeof (TrafficLightData));
  1264.         if (pTrafficLightData != nil)
  1265.         {
  1266.             pTrafficLightData->trafficLightWindowRef = trafficLightWindowRef;
  1267.             pTrafficLightData->avtDriverID = avtDriverID;
  1268.             pTrafficLightData->stopped = true;
  1269.         }
  1270.         else
  1271.         {
  1272.             err = memFullErr;
  1273.         }
  1274.     }
  1275.  
  1276.     // Open connection to driver.
  1277.     if (err == noErr)
  1278.         err = OpenAVTDriver (avtDriverID);
  1279.  
  1280.     // Store traffic light data in window ref con.
  1281.     if (err == noErr)
  1282.         SetWRefCon (trafficLightWindowRef, (long) pTrafficLightData);
  1283.  
  1284.     // Add traffic light to list or clean up on error.
  1285.     if (err == noErr)
  1286.     {
  1287.         pTrafficLightData->pNextTrafficLightData =
  1288.             gpAVTTrafficLightAppData->trafficLightDataList;
  1289.         gpAVTTrafficLightAppData->trafficLightDataList =
  1290.             pTrafficLightData;
  1291.     }
  1292.     else
  1293.     {
  1294.         if (pTrafficLightData != nil)
  1295.             DisposePtr ((Ptr) pTrafficLightData);
  1296.  
  1297.         if (trafficLightWindowRef != kInvalidWindowRef)
  1298.             CloseWindow (trafficLightWindowRef);
  1299.     }
  1300.  
  1301.     return (err);
  1302. }
  1303.  
  1304.  
  1305. ////////////////////////////////////////////////////////////////////////////////
  1306. //
  1307. // RemoveTrafficLight
  1308. //
  1309. //   This routine removes the traffic light window for the given driver.
  1310. //
  1311.  
  1312. static OSErr    RemoveTrafficLight(
  1313.     AVTDriverID                    avtDriverID)
  1314. {
  1315.     TrafficLightDataPtr            pTrafficLightData;
  1316.     Boolean                        found;
  1317.     OSErr                        err = noErr;
  1318.  
  1319.     // Find traffic light for given driver.
  1320.     pTrafficLightData = FindTrafficLightFromAVTDriver (avtDriverID);
  1321.     if (pTrafficLightData != nil)
  1322.         found = true;
  1323.     else
  1324.         found = false;
  1325.  
  1326.     // Stop playing snap shot.
  1327.     if (found)
  1328.     {
  1329.         if (pTrafficLightData->snapShotPlaying)
  1330.             StopSnapShot ();
  1331.     }
  1332.  
  1333.     // Close connection to driver.
  1334.     if (found)
  1335.         CloseAVTDriver (avtDriverID);
  1336.  
  1337.     // Close the traffic light window.
  1338.     if (found)
  1339.         CloseWindow (pTrafficLightData->trafficLightWindowRef);
  1340.  
  1341.     // Remove the traffic light data from our list.
  1342.     if (found)
  1343.         RemoveTrafficLightFromList (pTrafficLightData);
  1344.  
  1345.     return (err);
  1346. }
  1347.  
  1348.  
  1349. ////////////////////////////////////////////////////////////////////////////////
  1350. //
  1351. // CloseTrafficLightWindow
  1352. //
  1353. //   This routine closes the given traffic light window.
  1354. //
  1355.  
  1356. static OSErr    CloseTrafficLightWindow(
  1357.     WindowRef                    windowRef)
  1358. {
  1359.     TrafficLightDataPtr            pTrafficLightData;
  1360.     OSErr                        err = noErr;
  1361.  
  1362.     // Get traffic light data.
  1363.     pTrafficLightData = (TrafficLightDataPtr) GetWRefCon (windowRef);
  1364.  
  1365.     // Remove the traffic light.
  1366.     err = RemoveTrafficLight (pTrafficLightData->avtDriverID);
  1367.     
  1368.     return (err);
  1369. }
  1370.  
  1371.  
  1372. ////////////////////////////////////////////////////////////////////////////////
  1373. //
  1374. // DrawTrafficLight
  1375. //
  1376. //   This routine draws the given traffic light window.
  1377. //
  1378.  
  1379. static OSErr    DrawTrafficLight(
  1380.     WindowRef                    windowRef)
  1381. {
  1382.     TrafficLightDataPtr            pTrafficLightData;
  1383.     GrafPtr                        pWindowPort;
  1384.     OSErr                        err = noErr;
  1385.  
  1386.     // Get traffic light data.
  1387.     pTrafficLightData = (TrafficLightDataPtr) GetWRefCon (windowRef);
  1388.  
  1389.     // Get window's graf port.
  1390.     pWindowPort = (GrafPtr) GetWindowPort (windowRef);
  1391.  
  1392.     // Set port to the window's port.
  1393.     SetPortWindowPort (windowRef);
  1394.  
  1395.     // Clear window.
  1396.     EraseRect (&(pWindowPort->portRect));
  1397.  
  1398.     // Draw stop light.
  1399.     if (pTrafficLightData->stopped)
  1400.         ForeColor (redColor);
  1401.     else
  1402.         ForeColor (blackColor);
  1403.     PaintOval (&(gpAVTTrafficLightAppData->stopRect));
  1404.     ForeColor (blackColor);
  1405.     FrameOval (&(gpAVTTrafficLightAppData->stopRect));
  1406.  
  1407.     // Draw go light.
  1408.     if (pTrafficLightData->stopped)
  1409.         ForeColor (blackColor);
  1410.     else
  1411.         ForeColor (greenColor);
  1412.     PaintOval (&(gpAVTTrafficLightAppData->goRect));
  1413.     ForeColor (blackColor);
  1414.     FrameOval (&(gpAVTTrafficLightAppData->goRect));
  1415.  
  1416.     return (err);
  1417. }
  1418.  
  1419.  
  1420. ////////////////////////////////////////////////////////////////////////////////
  1421. //
  1422. // SetTrafficLightState
  1423. //
  1424. //   This routine sets the state of the given traffic light window.
  1425. //
  1426.  
  1427. static OSErr    SetTrafficLightState(
  1428.     WindowRef                    windowRef,
  1429.     Boolean                        stopped)
  1430. {
  1431.     TrafficLightDataPtr            pTrafficLightData;
  1432.     AVTPlayParams                avtPlayParams;
  1433.     AVTStopParams                avtStopParams;
  1434.     GrafPtr                        pWindowPort;
  1435.     OSErr                        err = noErr;
  1436.  
  1437.     // Get traffic light data.
  1438.     pTrafficLightData = (TrafficLightDataPtr) GetWRefCon (windowRef);
  1439.  
  1440.     // Do something only if the state has changed.
  1441.     if (stopped != pTrafficLightData->stopped)
  1442.     {
  1443.         if (stopped)
  1444.         {
  1445.             avtStopParams.avtInterfaceParams.interfaceSelector =
  1446.                 kAVTransportStop;
  1447.             err = CallAVTDriver
  1448.                     (pTrafficLightData->avtDriverID,
  1449.                      (AVTInterfaceParamsPtr) &avtStopParams);
  1450.         }
  1451.         else
  1452.         {
  1453.             avtPlayParams.avtInterfaceParams.interfaceSelector =
  1454.                 kAVTransportPlay;
  1455.             err = CallAVTDriver
  1456.                     (pTrafficLightData->avtDriverID,
  1457.                      (AVTInterfaceParamsPtr) &avtPlayParams);
  1458.         }
  1459.  
  1460.         // Set new state.
  1461.         if (err == noErr)
  1462.             pTrafficLightData->stopped = stopped;
  1463.  
  1464.         // Force window update.
  1465.         if (err == noErr)
  1466.         {
  1467.             pWindowPort = (GrafPtr) GetWindowPort (windowRef);
  1468.             SetPortWindowPort (windowRef);
  1469.             InvalRect (&(pWindowPort->portRect));
  1470.         }
  1471.     }
  1472.  
  1473.     return (err);
  1474. }
  1475.  
  1476.  
  1477. ////////////////////////////////////////////////////////////////////////////////
  1478. //
  1479. // GetTrafficLightState
  1480. //
  1481. //   This routine gets the state of the given traffic light window.
  1482. //
  1483.  
  1484. static Boolean    GetTrafficLightState(
  1485.     WindowRef                    windowRef)
  1486. {
  1487.     TrafficLightDataPtr            pTrafficLightData;
  1488.  
  1489.     // Get traffic light data.
  1490.     pTrafficLightData = (TrafficLightDataPtr) GetWRefCon (windowRef);
  1491.  
  1492.     return (pTrafficLightData->stopped);
  1493. }
  1494.  
  1495.  
  1496. ////////////////////////////////////////////////////////////////////////////////
  1497. //
  1498. // UpdateWindow
  1499. //
  1500. //   This routine updates the given window.
  1501. //
  1502.  
  1503. static OSErr    UpdateWindow(
  1504.     WindowRef                    windowRef)
  1505. {
  1506.     Boolean                        updateNeeded,
  1507.                                 preparedUpdate;
  1508.     OSErr                        err = noErr;
  1509.  
  1510.     // Prepare window for updating.
  1511.     err = PrepareWindowForUpdating (windowRef, &updateNeeded);
  1512.     if (err == noErr)
  1513.         preparedUpdate = true;
  1514.     else
  1515.         preparedUpdate = false;
  1516.  
  1517.     // Draw the window.
  1518.     if ((err == noErr) && (updateNeeded))
  1519.         err = DrawTrafficLight (windowRef);
  1520.  
  1521.     // Release the window from updating.
  1522.     if (preparedUpdate)
  1523.         ReleaseWindowFromUpdating (windowRef);
  1524.  
  1525.     return (err);
  1526. }
  1527.  
  1528.  
  1529. ////////////////////////////////////////////////////////////////////////////////
  1530. //
  1531. // UpdateMenus
  1532. //
  1533. //   This routine sets up the menus for the front most window.
  1534. //
  1535.  
  1536. static OSErr    UpdateMenus(void)
  1537. {
  1538.     WindowRef                    windowRef;
  1539.     MenuHandle                    hMenu;
  1540.     OSErr                        err = noErr;
  1541.  
  1542.     // Get reference to front most window.
  1543.     windowRef = FrontWindow ();
  1544.  
  1545.     // Get handle to file menu.
  1546.     hMenu = GetMenuHandle (kFileMenuID);
  1547.  
  1548.     // Close menu item should be enabled if there is a window open.
  1549.     if (windowRef != kInvalidWindowRef)
  1550.         EnableItem (hMenu, kCloseFileMenuItem);
  1551.     else
  1552.         DisableItem (hMenu, kCloseFileMenuItem);
  1553.  
  1554.     return (err);
  1555. }
  1556.  
  1557.  
  1558. ////////////////////////////////////////////////////////////////////////////////
  1559. //
  1560. // UpdateCursor
  1561. //
  1562. //   This routine sets the cursor to the correct image for the given mouse
  1563. // position.
  1564. //
  1565.  
  1566. static OSErr    UpdateCursor(
  1567.     Point                        mousePosition,
  1568.     RgnHandle                    hCursorRgn)
  1569. {
  1570.     WindowRef                    windowRef;
  1571.     GrafPtr                        pWindowPort;
  1572.     Rect                        windowPortRect;
  1573.     RgnHandle                    hArrowCursorRgn = nil,
  1574.                                 hPlusCursorRgn = nil;
  1575.     OSErr                        err = noErr;
  1576.  
  1577.     // Update if we're not in background.
  1578.     if (gpAVTTrafficLightAppData->inForeground)
  1579.     {
  1580.         // Get reference to front most window.
  1581.         windowRef = FrontWindow ();
  1582.  
  1583.         // Initialize cursor regions.
  1584.         hArrowCursorRgn = NewRgn ();
  1585.         hPlusCursorRgn = NewRgn ();
  1586.  
  1587.         // Set plus region to front most window if it's a traffic light.
  1588.         if (IsTrafficLightWindow (windowRef))
  1589.         {
  1590.             // Get window's port and port rect.
  1591.             pWindowPort = (GrafPtr) GetWindowPort (windowRef);
  1592.  
  1593.             // Set plus region to visible portion of traffic light window.
  1594.             SetPortWindowPort (windowRef);
  1595.             SetOrigin (-(pWindowPort->portBits.bounds.left),
  1596.                        -(pWindowPort->portBits.bounds.top));
  1597.             windowPortRect = pWindowPort->portRect;
  1598.             RectRgn (hPlusCursorRgn, &windowPortRect);
  1599.             SectRgn (hPlusCursorRgn, pWindowPort->visRgn, hPlusCursorRgn);
  1600.             SetOrigin (0, 0);
  1601.         }
  1602.  
  1603.         // Set arrow region to everywhere except the other cursor regions.
  1604.         SetRectRgn (hArrowCursorRgn,
  1605.                     kExtremeNeg,
  1606.                     kExtremeNeg,
  1607.                     kExtremePos,
  1608.                     kExtremePos);
  1609.         DiffRgn (hArrowCursorRgn, hPlusCursorRgn, hArrowCursorRgn);
  1610.  
  1611.         // Change the cursor image and region.
  1612.         if (PtInRgn (mousePosition, hPlusCursorRgn))
  1613.         {
  1614.             SetCursor (*GetCursor (plusCursor));
  1615.             CopyRgn (hPlusCursorRgn, hCursorRgn);
  1616.         }
  1617.         else
  1618.         {
  1619.             SetCursor (&(gpAVTTrafficLightAppData->qdGlobals.arrow));
  1620.             CopyRgn (hArrowCursorRgn, hCursorRgn);
  1621.         }
  1622.     }
  1623.  
  1624.     // Clean up.
  1625.     if (hArrowCursorRgn != nil)
  1626.         DisposeRgn (hArrowCursorRgn);
  1627.     if (hPlusCursorRgn != nil)
  1628.         DisposeRgn (hPlusCursorRgn);
  1629.  
  1630.     return (err);
  1631. }
  1632.  
  1633.  
  1634. ////////////////////////////////////////////////////////////////////////////////
  1635. //
  1636. // IsTrafficLightWindow
  1637. //
  1638. //   This routine returns true if the given window is a traffic light.
  1639. //
  1640.  
  1641. static Boolean    IsTrafficLightWindow(
  1642.     WindowRef                    windowRef)
  1643. {
  1644.     // If the window is a user window, it's a traffic light.
  1645.     if (GetWindowKind (windowRef) == kApplicationWindowKind)
  1646.         return (true);
  1647.     else
  1648.         return (false);
  1649. }
  1650.  
  1651.  
  1652. ////////////////////////////////////////////////////////////////////////////////
  1653. //
  1654. // GetMousePosition
  1655. //
  1656. //   This routine returns the current position of the mouse.
  1657. //
  1658.  
  1659. static void    GetMousePosition(
  1660.     Point                        *pMousePosition)
  1661. {
  1662.     EventRecord                    eventRecord;
  1663.  
  1664.     // Get mouse position from event manager.
  1665.     OSEventAvail (0, &eventRecord);
  1666.     *pMousePosition = eventRecord.where;
  1667. }
  1668.  
  1669.  
  1670. ////////////////////////////////////////////////////////////////////////////////
  1671. //
  1672. // HandleOpenApplicationEvent
  1673. //
  1674. //   This routine handles open application events.
  1675. //
  1676.  
  1677. static pascal OSErr    HandleOpenApplicationEvent(
  1678.     AppleEvent                    *theAppleEvent,
  1679.     AppleEvent                    *reply,
  1680.     long                        handlerRefcon)
  1681. {
  1682.     OSErr                        err = noErr;
  1683.  
  1684.     return (err);
  1685. }
  1686.  
  1687.  
  1688. ////////////////////////////////////////////////////////////////////////////////
  1689. //
  1690. // HandleOpenDocumentsEvent
  1691. //
  1692. //   This routine handles open documents events.
  1693. //zzz should we return an error?
  1694. //
  1695.  
  1696. static pascal OSErr    HandleOpenDocumentsEvent(
  1697.     AppleEvent                    *theAppleEvent,
  1698.     AppleEvent                    *reply,
  1699.     long                        handlerRefcon)
  1700. {
  1701.     OSErr                        err = noErr;
  1702.  
  1703.     return (err);
  1704. }
  1705.  
  1706.  
  1707. ////////////////////////////////////////////////////////////////////////////////
  1708. //
  1709. // HandlePrintDocumentsEvent
  1710. //
  1711. //   This routine handles print documents events.
  1712. //zzz should we return an error?
  1713. //
  1714.  
  1715. static pascal OSErr    HandlePrintDocumentsEvent(
  1716.     AppleEvent                    *theAppleEvent,
  1717.     AppleEvent                    *reply,
  1718.     long                        handlerRefcon)
  1719. {
  1720.     OSErr                        err = noErr;
  1721.  
  1722.     return (err);
  1723. }
  1724.  
  1725.  
  1726. ////////////////////////////////////////////////////////////////////////////////
  1727. //
  1728. // HandleQuitApplicationEvent
  1729. //
  1730. //   This routine handles quit application events.
  1731. //
  1732.  
  1733. static pascal OSErr    HandleQuitApplicationEvent(
  1734.     AppleEvent                    *theAppleEvent,
  1735.     AppleEvent                    *reply,
  1736.     long                        handlerRefcon)
  1737. {
  1738.     OSErr                        err = noErr;
  1739.  
  1740.     // Quit the application.
  1741.     QuitApplication ();
  1742.  
  1743.     return (err);
  1744. }
  1745.  
  1746.  
  1747. ////////////////////////////////////////////////////////////////////////////////
  1748. //
  1749. // HandleDeviceAddedEvent
  1750. //
  1751. //   This routine handles AV transport control device added events.
  1752. //
  1753.  
  1754. static pascal OSErr    HandleDeviceAddedEvent(
  1755.     AppleEvent                    *theAppleEvent,
  1756.     AppleEvent                    *reply,
  1757.     long                        handlerRefcon)
  1758. {
  1759.     AVTDriverID                    avtDriverID;
  1760.     DescType                    returnedType;
  1761.     Size                        returnedSize;
  1762.     Boolean                        inList;
  1763.     OSErr                        err = noErr;
  1764.  
  1765.     // Get driver ID from apple event.
  1766.     err = AEGetParamPtr (theAppleEvent,
  1767.                          kAEAVTDriverIDKey,
  1768.                          kAEAVTDriverIDType,
  1769.                          &returnedType,
  1770.                          &avtDriverID,
  1771.                          sizeof (AVTDriverID),
  1772.                          &returnedSize);
  1773.  
  1774.     // Check if avt driver is in our list.  This will happen if device was
  1775.     // connected, opened, disconnected, and reconnected without being closed.
  1776.     // If it's in our list, do not create a new traffic light.
  1777.     if (err == noErr)
  1778.     {
  1779.         if (FindTrafficLightFromAVTDriver (avtDriverID))
  1780.             inList = true;
  1781.         else
  1782.             inList = false;
  1783.     }
  1784.  
  1785.     // Create traffic light for added device.
  1786.     if ((err == noErr) && (!inList))
  1787.         err = CreateTrafficLight (avtDriverID);
  1788.  
  1789.     return (err);
  1790. }
  1791.  
  1792.  
  1793. ////////////////////////////////////////////////////////////////////////////////
  1794. //
  1795. // HandleDeviceRemovedEvent
  1796. //
  1797. //   This routine handles AV transport control device removed events.
  1798. //
  1799.  
  1800. static pascal OSErr    HandleDeviceRemovedEvent(
  1801.     AppleEvent                    *theAppleEvent,
  1802.     AppleEvent                    *reply,
  1803.     long                        handlerRefcon)
  1804. {
  1805.     AVTDriverID                    avtDriverID;
  1806.     DescType                    returnedType;
  1807.     Size                        returnedSize;
  1808.     OSErr                        err = noErr;
  1809.  
  1810.     // Get driver ID from apple event.
  1811.     err = AEGetParamPtr (theAppleEvent,
  1812.                          kAEAVTDriverIDKey,
  1813.                          kAEAVTDriverIDType,
  1814.                          &returnedType,
  1815.                          &avtDriverID,
  1816.                          sizeof (AVTDriverID),
  1817.                          &returnedSize);
  1818.  
  1819.     // Create traffic light for removed device.
  1820.     if (err == noErr)
  1821.         err = RemoveTrafficLight (avtDriverID);
  1822.  
  1823.     return (err);
  1824. }
  1825.  
  1826.  
  1827. ////////////////////////////////////////////////////////////////////////////////
  1828. //
  1829. // FindTrafficLightFromAVTDriver
  1830. //
  1831. //   This routine searches for the traffic light corresponding to the given
  1832. // AVT driver ID.
  1833. //
  1834.  
  1835. static TrafficLightDataPtr    FindTrafficLightFromAVTDriver(
  1836.     AVTDriverID                    avtDriverID)
  1837. {
  1838.     TrafficLightDataPtr            pTrafficLightData,
  1839.                                 pPrevTrafficLightData;
  1840.     Boolean                        found;
  1841.     OSErr                        err = noErr;
  1842.  
  1843.     // Find traffic light for given driver.
  1844.     pTrafficLightData = gpAVTTrafficLightAppData->trafficLightDataList;
  1845.     pPrevTrafficLightData = nil;
  1846.     found = false;
  1847.     while ((pTrafficLightData != nil) && (!found))
  1848.     {
  1849.         if (pTrafficLightData->avtDriverID == avtDriverID)
  1850.         {
  1851.             found = true;
  1852.         }
  1853.         else
  1854.         {
  1855.             pPrevTrafficLightData = pTrafficLightData;
  1856.             pTrafficLightData = pTrafficLightData->pNextTrafficLightData;
  1857.         }
  1858.     }
  1859.  
  1860.     return (pTrafficLightData);
  1861. }
  1862.  
  1863.  
  1864. ////////////////////////////////////////////////////////////////////////////////
  1865. //
  1866. // RemoveTrafficLightFromList
  1867. //
  1868. //   This routine removes the given traffic light data record from our list.
  1869. //
  1870.  
  1871. static OSErr    RemoveTrafficLightFromList(
  1872.     TrafficLightDataPtr            pTrafficLightData)
  1873. {
  1874.     TrafficLightDataPtr            pSearchTrafficLightData,
  1875.                                 pPrevTrafficLightData;
  1876.     Boolean                        found;
  1877.     OSErr                        err = noErr;
  1878.  
  1879.     // Find previous traffic light data record.
  1880.     pSearchTrafficLightData = gpAVTTrafficLightAppData->trafficLightDataList;
  1881.     pPrevTrafficLightData = nil;
  1882.     found = false;
  1883.     while ((pSearchTrafficLightData != nil) && (!found))
  1884.     {
  1885.         if (pSearchTrafficLightData == pTrafficLightData)
  1886.         {
  1887.             found = true;
  1888.         }
  1889.         else
  1890.         {
  1891.             pPrevTrafficLightData = pSearchTrafficLightData;
  1892.             pSearchTrafficLightData = pSearchTrafficLightData->pNextTrafficLightData;
  1893.         }
  1894.     }
  1895.  
  1896.     // Remove the traffic light data from our list.
  1897.     if (found)
  1898.     {
  1899.         if (pPrevTrafficLightData != nil)
  1900.         {
  1901.             pPrevTrafficLightData->pNextTrafficLightData =
  1902.                 pTrafficLightData->pNextTrafficLightData;
  1903.         }
  1904.         else
  1905.         {
  1906.             gpAVTTrafficLightAppData->trafficLightDataList =
  1907.                 pTrafficLightData->pNextTrafficLightData;
  1908.         }
  1909.  
  1910.         DisposePtr ((Ptr) pTrafficLightData);
  1911.     }
  1912.  
  1913.     return (err);
  1914. }
  1915.  
  1916.  
  1917. ////////////////////////////////////////////////////////////////////////////////
  1918. ////////////////////////////////////////////////////////////////////////////////
  1919. //
  1920. // Window managing routines.
  1921. //
  1922. //   Code that needs to use window records goes here.
  1923. //
  1924. ////////////////////////////////////////////////////////////////////////////////
  1925. ////////////////////////////////////////////////////////////////////////////////
  1926.  
  1927. ////////////////////////////////////////////////////////////////////////////////
  1928. //
  1929. // PrepareWindowForUpdating
  1930. //
  1931. //   This routine prepares the given window for updating.
  1932. //
  1933.  
  1934. static OSErr    PrepareWindowForUpdating(
  1935.     WindowRef                    windowRef,
  1936.     Boolean                        *pUpdateNeeded)
  1937. {
  1938.     GrafPtr                        pWindowPort;
  1939.     OSErr                        err = noErr;
  1940.  
  1941.     // Get window's port.
  1942.     pWindowPort = (GrafPtr) GetWindowPort (windowRef);
  1943.  
  1944.     // Call window manager to begin update.
  1945.     BeginUpdate (windowRef);
  1946.  
  1947.     // Check if window needs updating.
  1948.     if (pUpdateNeeded != nil)
  1949.     {
  1950.         if (EmptyRgn (pWindowPort->visRgn))
  1951.             *pUpdateNeeded = false;
  1952.         else
  1953.             *pUpdateNeeded = true;
  1954.     }
  1955.  
  1956.     return (err);
  1957. }
  1958.  
  1959.  
  1960. ////////////////////////////////////////////////////////////////////////////////
  1961. //
  1962. // ReleaseWindowFromUpdating
  1963. //
  1964. //   This routine releases the given window from updating.
  1965. //
  1966.  
  1967. static OSErr    ReleaseWindowFromUpdating(
  1968.     WindowRef                    windowRef)
  1969. {
  1970.     OSErr                        err = noErr;
  1971.  
  1972.     // Call window manager to end update.
  1973.     EndUpdate (windowRef);
  1974.  
  1975.     return (err);
  1976. }
  1977.